<%
'######################################################################
'## ab.tpl.asp
'## -------------------------------------------------------------------
'## Feature     :   AspBox Templates Class
'## Version     :   v1.0.1
'## Author      :   Lajox(lajox@19www.com)
'## Update Date :   2012/03/01 23:31
'## Description :   Use Templates with AspBox
'######################################################################

Class Cls_AB_Tpl
	Private s_html, s_ohtml, s_unknown, s_dict, s_charset, s_path, s_m, s_ms, s_me
	Private o_tag, o_blockfull_b, o_blockdata, o_blockdata_b, o_block, o_blocks, o_update, o_attr, Fn
	Private b_asp, b_update_block, b_var_bef
	Private s_bx, s_by, s_var_bef, s_rq_show
	Private i_errCode, s_errMsg

	Private Sub class_Initialize
		On Error Resume Next
		s_dict = AB.dictName
		Set o_tag = Server.CreateObject(s_dict) : o_tag.CompareMode = 1
		Set o_blockfull_b = Server.CreateObject(s_dict) : o_blockfull_b.CompareMode = 1
		Set o_blockdata = Server.CreateObject(s_dict) : o_blockdata.CompareMode = 1
		Set o_blockdata_b = Server.CreateObject(s_dict) : o_blockdata_b.CompareMode = 1
		Set o_block = Server.CreateObject(s_dict) : o_block.CompareMode = 1
		Set o_blocks = Server.CreateObject(s_dict) : o_blocks.CompareMode = 1
		Set o_update = Server.CreateObject(s_dict) : o_update.CompareMode = 1
		Set o_attr = Server.CreateObject(s_dict) : o_attr.CompareMode = 1
		Set Fn = New Cls_AB_Tpl_Fn
		i_errCode = 0
		s_charset = AB.CharSet
		s_path = ""
		s_file = ""
		s_unknown = "keep"
		s_m = "{*}"
		getMaskSE s_m
		b_asp = False
		b_update_block = False
		s_html = ""
		s_ohtml = ""
		s_bx = "<block:" : s_by = ">"
		s_var_bef = "$" '区别变量名前缀
		b_var_bef = False '是否严格要求变量名前缀
		s_rq_show = "ljx_tplshow_ok"
	End Sub

	Private Sub Class_Terminate
		Set o_tag = Nothing
		Set o_blockfull_b = Nothing
		Set o_blockdata = Nothing
		Set o_blockdata_b = Nothing
		Set o_block = Nothing
		Set o_blocks = Nothing
		Set o_update = Nothing
		Set o_attr = Nothing
		Set Fn = Nothing
		On Error Goto 0
	End Sub

	'------------------------------------------------------------------------------------------
	'# AB.Tpl.FilePath 属性 [可读/写]
	'# @syntax: AB.Tpl.FilePath = path
	'# @return: String (字符串) 模板文件所在文件夹
	'# @dowhat: 设置和获取 模板文件所在文件夹，支持绝对路径和相对路径 [默认值：空]
	'--DESC------------------------------------------------------------------------------------
	'# @param path : String (字符串) 模板文件所在文件夹
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "Tpl"
	'# AB.Tpl.FilePath = "../tpl/html/" '默认值为空
	'------------------------------------------------------------------------------------------

	Public Property Get FilePath
		FilePath = s_path
	End Property

	Public Property Let FilePath(ByVal f)
		If Right(f,1)<>"/" Then f = f & "/"
		s_path = f
	End Property

	'------------------------------------------------------------------------------------------
	'# AB.Tpl.File 属性 [只写]
	'# @syntax: AB.Tpl.File = file
	'# @return: String (字符串) 加载的模板文件
	'# @dowhat: 设置要加载的模板(载入模板)
	'--DESC------------------------------------------------------------------------------------
	'# @param file : String (字符串) 要加载的模板文件
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "Tpl"
	'# AB.Tpl.File = "tpl.html"   ''这将等同于：tpl.Load "tpl.html"
	'# AB.Tpl.Show()
	'------------------------------------------------------------------------------------------

	Public Property Let [File](ByVal f)
		Load(f)
	End Property

	'------------------------------------------------------------------------------------------
	'# AB.Tpl.Source 属性 [只写]
	'# @syntax: AB.Tpl.Source = string
	'# @alias:  AB.Tpl.Src = string
	'# @return: String (字符串) 加载的内容模板
	'# @dowhat: 设置载入的内容模板 (注：设置的模板文件 和 内容模板，二者只取其一，以最后一次为准)
	'--DESC------------------------------------------------------------------------------------
	'# @param string : String (字符串) 要加载的内容模板
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "tpl" '加载tpl核心
	'# Dim tpl : Set tpl = AB.Tpl.New '创建一个Tpl对象
	'# 'tpl.TagMask = "{*}" '默认为{*}
	'# tpl.Source = "<style>html{margin:0;padding:0;}</style>hello.<br>{test}"
	'# ''上面这将等同于：tpl.LoadStr "<style>html{margin:0;padding:0;}hello.<br>{test}"
	'# tpl.TagStr "test", "<div id=""test"">测试内容</div>"
	'# tpl.Show() '输出内容, 等同于 AB.C.Print tpl.GetHtml()
	'# Set tpl = Nothing '释放Tpl对象
	'# '上面例子输出结果：<style>html{margin:0;padding:0;}</style>hello.<br><div id=""test"">测试内容</div>
	'------------------------------------------------------------------------------------------

	Public Property Let [Source](ByVal s)
		LoadStr(s)
	End Property
	Public Property Let Src(ByVal s): LoadStr(s): End Property

	'------------------------------------------------------------------------------------------
	'# AB.Tpl.TagMask 属性
	'# @syntax: AB.Tpl.TagMask = string
	'# @return: String (字符串) 模板标签的样式
	'# @dowhat: 设置和获取模板标签的样式，此属性可读可写
	'--DESC------------------------------------------------------------------------------------
	'# @param string : String (字符串) 模板标签的样式
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "Tpl"
	'# AB.Tpl.TagMask = "{$*$}" '例：{{*}}, {$*$}, 默认为{*}
	'------------------------------------------------------------------------------------------

	Public Property Get TagMask
		TagMask = s_m
	End Property

	Public Property Let TagMask(ByVal m)
		s_m = m
		getMaskSE s_m
	End Property

	'------------------------------------------------------------------------------------------
	'# AB.Tpl.Tag 属性 [只写]
	'# @syntax: AB.Tpl.Tag(str) = value
	'# @alias: AB.Tpl.D(str) = value
	'# @alias: AB.Tpl.Assign str, value
	'# @return: String (字符串) 取代标签的变量值
	'# @dowhat: 设置标签的变量值
	'--DESC------------------------------------------------------------------------------------
	'# @param value : Any (任意类型) 取代标签的变量值
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "tpl" '加载tpl核心
	'# Dim tpl : Set tpl = AB.Tpl.New '创建一个Tpl对象
	'# 'tpl.TagMask = "{*}" '默认为{*}
	'# tpl.Source = "<style>html{margin:0;padding:0;}</style>hello.<br>{test}"
	'# Dim Temp : Temp = "This is demo."
	'# tpl.Tag("test") = Temp ''这将等同于：tpl.Assign "test", Temp
	'# tpl.Show() '输出模板内容
	'# Set tpl = Nothing '释放Tpl对象
	'# '上面例子输出结果：<style>html{margin:0;padding:0;}</style>hello.<br>This is demo.
	'------------------------------------------------------------------------------------------

	Public Property Let Tag(ByVal s, ByVal v)
		Assign s, v
	End Property
	Public Property Let D(ByVal s, ByVal v) : Assign s, v : End Property

	Public Property Get Tag(ByVal s)
		If o_tag.Exists(s) Then
			Tag = o_tag.Item(s)
		Else
			Tag = ""
		End If
	End Property
	Public Property Get D(ByVal s) : D = Tag(s) : End Property

	'------------------------------------------------------------------------------------------
	'# AB.Tpl.AspEnable 属性 [可读/写]
	'# @syntax: AB.Tpl.AspEnable = bool
	'# @return: Boolean (布尔值) True/False
	'# @dowhat: 设置和获取 是否允许在模板文件中使用ASP代码 [默认值：False]
	'--DESC------------------------------------------------------------------------------------
	'# @param bool : Boolean (布尔值) True/False
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "Tpl"
	'# AB.Tpl.AspEnable = True '默认值 False
	'------------------------------------------------------------------------------------------

	Public Property Get AspEnable
		AspEnable = b_asp
	End Property

	Public Property Let AspEnable(ByVal b)
		b_asp = b
	End Property

	'------------------------------------------------------------------------------------------
	'# AB.Tpl.TagUnknown 属性 [可读/写]
	'# @syntax: AB.Tpl.TagUnknown = string
	'# @return: String (字符串) 未定义的模板标签的处理方式(一般为： remove, keep, comment)
	'# @dowhat: 设置和获取未定义的模板标签的处理方式 [默认值：keep]
	'--DESC------------------------------------------------------------------------------------
	'# @param string : String (字符串) 未定义的模板标签的处理方式, 默认为 keep
	'#  如何处理未替换的标签,"keep"-保留，"remove"-移除，"comment"-转成注释
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "Tpl"
	'# AB.Tpl.TagUnknown = "comment" '默认为 keep
	'------------------------------------------------------------------------------------------

	Public Property Get TagUnknown
		TagUnknown = s_unknown
	End Property

	Public Property Let TagUnknown(ByVal s)
		Select Case LCase(s)
			Case "1", "remove"
				s_unknown = "remove"
			Case "2", "comment"
				s_unknown = "comment"
			Case Else
				s_unknown = "keep"
		End Select
	End Property

	'------------------------------------------------------------------------------------------
	'# AB.Tpl.New 方法
	'# @syntax: Set tpl = AB.Tpl.New
	'# @return: Object (ASP对象)
	'# @dowhat: 创建一个 Tpl 核心对象
	'--DESC------------------------------------------------------------------------------------
	'# @param: none
	'--DEMO------------------------------------------------------------------------------------
	'# Dim tpl : Set tpl = AB.Tpl.New 	'创建Tpl核心对象
	'------------------------------------------------------------------------------------------

	Public Function [New]()
		Set [New] = New Cls_AB_Tpl
	End Function

	Public Function Attr(ByVal s)
		If Not o_attr.Exists(s) Then Exit Function
		Attr = o_attr.Item(s)
	End Function

	'------------------------------------------------------------------------------------------
	'# AB.Tpl.Load 方法
	'# @syntax: AB.Tpl.Load filePath
	'# @return: 无返回值
	'# @dowhat: 用标准模式载入模板文件
	'--DESC------------------------------------------------------------------------------------
	'# @param filePath : 模板文件路径
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "tpl"
	'# '模板文件所在文件夹，支持绝对路径和相对路径
	'# AB.Tpl.FilePath = "html"
	'# '加载模板
	'# AB.Tpl.Load "tpl.html"
	'# '也可以用下面这种方式加载模板
	'# 'AB.Tpl.File = "tpl.html"
	'# AB.Tpl.Show
	'------------------------------------------------------------------------------------------

	Public Sub Load(ByVal f)
		s_html = LoadInc(s_path & f,"")
		s_ohtml = s_html
		Ready()
	End Sub

	'------------------------------------------------------------------------------------------
	'# AB.Tpl.LoadStr 方法
	'# @syntax: AB.Tpl.LoadStr string
	'# @return: 无返回值
	'# @dowhat: 设置载入的内容模板
	'--DESC------------------------------------------------------------------------------------
	'# @param string : 设置载入的内容模板
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "tpl" '加载tpl核心
	'# Dim tpl : Set tpl = AB.Tpl.New '创建一个Tpl对象
	'# tpl.TagMask = "{{*}}"
	'# tpl.LoadStr "<h3>模板测试</h3><br><h4>标签{type}值为： <strong>{{type}}</strong><br>{{#if @count!=''}}标签{count}值为 <strong>{{count}}</strong><br>{{/#if}}标签{count}{{#if @top>0}}值大于0，值为： <strong>{{top}}</strong> {{#else}}值是不大于0的。{{/#if}}</h4><br>{{table}}"
	'# tpl "top", 0
	'# 'tpl "count", 5
	'# tpl.TagStr "table", "<table><tr><td>{{name}}</td></tr><tr><td>{{value}}</td></tr></table>"
	'# tpl "type", "Type123"
	'# tpl "name", "TestName"
	'# tpl "Value", 123456
	'# 'ab.c.print tpl.GetHtml()
	'# tpl.Show()
	'# Set tpl = Nothing '释放Tpl对象
	'------------------------------------------------------------------------------------------

	Public Sub LoadStr(ByVal s)
		s_html = s
		s_ohtml = s
		Ready()
	End Sub

	Public Sub Reload()
		o_tag.RemoveAll
		o_blockdata.RemoveAll
		o_blockdata_b.RemoveAll
		o_blockfull_b.RemoveAll
		o_block.RemoveAll
		o_blocks.RemoveAll
		o_attr.RemoveAll
		s_html = s_ohtml
		Ready()
	End Sub

	'------------------------------------------------------------------------------------------
	'# AB.Tpl.TagFile 方法
	'# @syntax: AB.Tpl.TagFile tag, filePath
	'# @return: 无返回值
	'# @dowhat: 用模板标签载入并替换为副模板文件内容
	'--DESC------------------------------------------------------------------------------------
	'# @param tag : 标签
	'# @param filePath : 副模板文件路径
	'--DEMO------------------------------------------------------------------------------------
	'# '加载tpl核心
	'# AB.Use "tpl"
	'# '模板文件所在文件夹，支持绝对路径和相对路径
	'# AB.Tpl.FilePath = "html"
	'# '加载模板,假设模板内容为：hello.<br>{table}
	'# AB.Tpl.Load "tpl.html"
	'# '将标签替换为副模板内容,假设副模板内容为：<table><tr><td>{name}</td></tr><tr><td>{value}</td></tr></table>
	'# AB.Tpl.TagFile "table", "inc/table.html"
	'# AB.Tpl "name", "TestName"
	'# AB.Tpl "Value", 123456
	'# AB.Tpl.Show
	'# '上面例子输出结果：hello.<br><table><tr><td>TestName</td></tr><tr><td>123456</td></tr></table>
	'------------------------------------------------------------------------------------------

	Public Sub TagFile(ByVal tag, ByVal f)
		LoadToTag tag,0,f
	End Sub

	'------------------------------------------------------------------------------------------
	'# AB.Tpl.TagStr 方法
	'# @syntax: AB.Tpl.TagStr tag, string
	'# @return: 无返回值
	'# @dowhat: 用模板标签替换模板内容
	'--DESC------------------------------------------------------------------------------------
	'# @param tag : 模板标签
	'# @param string : 设置模板内容
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "tpl" '加载tpl核心
	'# Dim tpl : Set tpl = AB.Tpl.New '创建一个Tpl对象
	'# 'tpl.TagMask = "{*}" '默认为{*}
	'# tpl.LoadStr "hello.<br>{table}"
	'# tpl.TagStr "table", "<table><tr><td>{name}</td></tr><tr><td>{value}</td></tr></table>"
	'# tpl "name", "TestName"
	'# tpl "Value", 123456
	'# tpl.Show()
	'# Set tpl = Nothing '释放Tpl对象
	'# '上面例子输出结果：hello.<br><table><tr><td>TestName</td></tr><tr><td>123456</td></tr></table>
	'------------------------------------------------------------------------------------------

	Public Sub TagStr(ByVal tag, ByVal s)
		LoadToTag tag,1,s
	End Sub

	Private Sub LoadToTag(ByVal tag, ByVal t, ByVal f)
		On Error Resume Next
		Dim s
		If t = 0 Then
			s = LoadInc(s_path & f,"")
		Else
			s = f
		End If
		If AB.C.Has(tag) Then
			s_html = AB.C.regReplace(s_html, s_ms & tag & s_me, s)
		Else
			s_html = s_html & s
		End If
		Ready()
		On Error Goto 0
	End Sub

	'------------------------------------------------------------------------------------------
	'# AB.Tpl.Assign 方法
	'# @syntax: AB.Tpl.Assign str, value [省略写法： AB.Tpl str, value ]
	'# @alias: AB.Tpl.Tag(str) = value
	'# @return: void
	'# @dowhat: 设置标签变量值
	'--DESC------------------------------------------------------------------------------------
	'# @param str : String (字符串) 标签名
	'# @param value : Any (任意类型) 标签值
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "tpl" '加载tpl核心
	'# Dim tpl : Set tpl = AB.Tpl.New '创建一个Tpl对象
	'# 'tpl.TagMask = "{*}" '默认为{*}
	'# tpl.Source = "<style>html{margin:0;padding:0;}</style>hello.<br>{test}"
	'# Dim Temp : Temp = "This is demo."
	'# tpl.Assign "test", Temp ''这将等同于：tpl.Tag("test") = Temp
	'# tpl.Show() '输出模板内容
	'# Set tpl = Nothing '释放Tpl对象
	'# '上面例子输出结果：<style>html{margin:0;padding:0;}</style>hello.<br>This is demo.
	'------------------------------------------------------------------------------------------

	Public Default Sub Assign(ByVal s, ByVal v)
		On Error Resume Next
		Dim i,f
		Select Case TypeName(v)
			Case "Recordset"
				If AB.C.Has(v) Then
					For i = 0 To v.Fields.Count - 1
						Assign s & "." & v.Fields(i).Name, v.Fields(i).Value
						Assign s & "." & i, v.Fields(i).Value
					Next
				End If
			Case "Dictionary" '字典
				If AB.C.Has(v) Then
					For Each i In v
						Assign s & "." & i, v.Item(i)
					Next
				End If
			Case "Cls_AB_List"
				If v.Size > 0 Then
					For i = 0 To v.End
						Assign s & "." & i, v(i)
						Assign s & "." & v.IndexHash(i), v(i)
					Next
				End If
			Case Else
				If AB.C.IsNul(v) Then v = ""
				If Not IsObject(v) Then v = Cstr(v)
				If o_tag.Exists(s) Then o_tag.Remove s
				o_tag.Add s, v
		End Select
		On Error Goto 0
	End Sub

	'------------------------------------------------------------------------------------------
	'# AB.Tpl.Append 方法
	'# @syntax: AB.Tpl.Append str, value
	'# @return: void
	'# @dowhat: 简单设置标签变量值(对于复杂数据,如 Rs对象 请用 AB.Tpl.Assign 方法)
	'--DESC------------------------------------------------------------------------------------
	'# @param str : String (字符串) 标签名
	'# @param value : String|Integer (字符串 或 int类型) 标签值
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "tpl" '加载tpl核心
	'# Dim tpl : Set tpl = AB.Tpl.New '创建一个Tpl对象
	'# 'tpl.TagMask = "{*}" '默认为{*}
	'# tpl.Source = "<style>html{margin:0;padding:0;}</style>hello.<br>{test}"
	'# Dim Temp : Temp = "This is demo."
	'# tpl.Append "test", Temp
	'# tpl.Show() '输出模板内容
	'# Set tpl = Nothing '释放Tpl对象
	'# '上面例子输出结果：<style>html{margin:0;padding:0;}</style>hello.<br>This is demo.
	'------------------------------------------------------------------------------------------

	Public Sub Append(ByVal s, ByVal v)
		On Error Resume Next
		If AB.C.IsNul(v) Then v = ""
		Dim tmp
		If o_tag.Exists(s) Then
			tmp = o_tag.Item(s) & Cstr(v)
			o_tag(s) = Cstr(tmp)
		Else
			o_tag.Add s, Cstr(v)
		End If
		On Error Goto 0
	End Sub

	'------------------------------------------------------------------------------------------
	'# AB.Tpl.SrcHtml 方法
	'# @syntax: content = AB.Tpl.SrcHtml()
	'# @return: String (字符串)
	'# @dowhat: 获取模版原始内容
	'--DESC------------------------------------------------------------------------------------
	'# @param : none
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "tpl" '加载tpl核心
	'# AB.Tpl.Source = "hello.<br>{test}"
	'# AB.Tpl "test", "This is demo."
	'# AB.C.Print AB.Tpl.SrcHtml() '输出模板原始内容: hello.<br>{test}
	'# AB.C.Print AB.Tpl.GetHtml() '输出模板解析后的内容: hello.<br>This is demo.
	'# 'AB.Tpl.Show() '输出模板解析后的内容: hello.<br>This is demo.
	'------------------------------------------------------------------------------------------

	Public Function SrcHtml()
		SrcHtml = s_ohtml
	End Function

	'------------------------------------------------------------------------------------------
	'# AB.Tpl.GetHtml 方法
	'# @syntax: content = AB.Tpl.GetHtml()
	'# @return: String (字符串)
	'# @dowhat: 获取模版解析的最终内容
	'--DESC------------------------------------------------------------------------------------
	'# @param : none
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "tpl" '加载tpl核心
	'# AB.Tpl.Source = "hello.<br>{test}"
	'# AB.Tpl "test", "This is demo."
	'# AB.C.Print AB.Tpl.GetHtml() '输出模板解析后的内容: hello.<br>This is demo.
	'# 'AB.Tpl.Show() '输出模板解析后的内容: hello.<br>This is demo.
	'------------------------------------------------------------------------------------------

	Public Function GetHtml()
		On Error Resume Next
		GetHtml = ParseHtml(s_html)
		On Error Goto 0
	End Function

	'------------------------------------------------------------------------------------------
	'# AB.Tpl.Show 方法
	'# @syntax: AB.Tpl.Show()
	'# @alias: AB.Tpl.Display()
	'# @return: void
	'# @dowhat: 输出模版解析的最终内容
	'--DESC------------------------------------------------------------------------------------
	'# @param : none
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "tpl" '加载tpl核心
	'# AB.Tpl.Source = "hello.<br>{test}"
	'# AB.Tpl "test", "This is demo."
	'# 'AB.C.Print AB.Tpl.GetHtml() '输出模板解析后的内容: hello.<br>This is demo.
	'# AB.Tpl.Show() '输出模板解析后的内容: hello.<br>This is demo.
	'------------------------------------------------------------------------------------------

	Public Sub Show()
		AB.C.Print GetHtml
	End Sub
	Public Sub Display() : AB.C.Print GetHtml : End Sub

	'------------------------------------------------------------------------------------------
	'# AB.Tpl.SaveAs 方法
	'# @syntax: AB.Tpl.SaveAs(filepath)
	'# @return: void
	'# @dowhat: 将解析内容生成为文件
	'--DESC------------------------------------------------------------------------------------
	'# @param filepath : String (字符串) 生成文件路径
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "tpl" '加载tpl核心
	'# AB.Tpl.Source = "hello.<br>{test}"
	'# AB.Tpl "test", "This is demo."
	'# AB.Tpl.SaveAs("/html/index.html") '生成模板文件,其内容为: hello.<br>This is demo.
	'------------------------------------------------------------------------------------------

	Public Sub SaveAs(ByVal p)
		AB.Use "Fso"
		Call AB.Fso.CreateFile(p,GetHtml)
	End Sub

	'准备就绪
	Public Sub Ready()
		s_html = SetBlocks(s_html)
	End Sub

	Public Function ParseHtml(Byval html)
		On Error Resume Next
		Dim ohtml : ohtml = html
		ohtml= Parse("block", ohtml) '<块>标签解析
		ohtml= Parse("block", ohtml) '<块>标签解析
		ohtml= Parse("common", ohtml) '<常用>标签解析
		ohtml= Parse_Unknown("block", ohtml) '<未知:块>标签解析
		ohtml= Parse_Unknown("common", ohtml) '<未知:常用>标签解析
		ohtml = Parse("if", ohtml) '<if>标签解析
		'ohtml = replace_html(ohtml)
		ohtml = AB.C.RegReplace(ohtml, "(<!--[\s]*)+Unknown (Tag|Block)[\s]*(.+?)([\s]*-->)+", "<!-- Unknown $2 $3 -->")
		ParseHtml = ohtml
		On Error Goto 0
	End Function

	'标签解析中心
	Public Function Parse(Byval mark, Byval html)
		On Error Resume Next
		Dim ohtml : ohtml = html
		Select Case Lcase(mark)
			Case "common" : '通用标签
				ohtml = ParseMark_Common(ohtml)
			Case "block" : 'e.g. {#:A}<li>{A.title} - {A.addtime}</li>{/#:A}
				ohtml = ParseMark_Block(ohtml)
			Case "if" :
				'asp style: If.. ElseIf .. Else .. End If
				'js style: {if condition} .. {elseif condition} .. {else} .. {/if}
				ohtml = ParseMark_If(ohtml)
			' Case "for" : 'For .. Next
				' ohtml = ParseMark_For(ohtml)
			' Case "while" : 'While .. Wend
				' ohtml = ParseMark_While(ohtml)
			' Case "loop" : 'Do .. Loop
				' ohtml = ParseMark_Loop(ohtml)
			' Case "eval" : 'eval运算赋值
				' ohtml = ParseMark_Eval(ohtml)
			' Case "comment" : '模版注释
				' ohtml = ParseMark_Comment(ohtml)
			' Case "echo" : '输出块
				' ohtml = ParseMark_Echo(ohtml)
		End Select
		ohtml = "" & ohtml & ""
		Parse = ohtml
		On Error Goto 0
	End Function

	'未知标签解析
	Public Function Parse_Unknown(Byval mark, Byval html)
		On Error Resume Next
		Dim ohtml : ohtml = html
		'If AB.C.IsNul(html) Then ohtml = s_html
		Select Case Lcase(mark)
			Case "common" : '通用标签
				ohtml = ParseMarkUnknown_Common(ohtml)
			Case "block" : 'e.g. {#:A}<li>{A.title} - {A.addtime}</li>{/#:A}
				ohtml = ParseMarkUnknown_Block(ohtml)
		End Select
		ohtml = "" & ohtml & ""
		Parse_Unknown = ohtml
		On Error Goto 0
	End Function

	'---- <common tag> process b --->>>
	'e.g.
	'标准写法: {$tag}
	'兼容旧版写法: {tag}

	Public Function ParseMark_Common(Byval html)
		On Error Resume Next
		Dim ohtml : ohtml = html
		Dim Matches, Match, rule, tag, attrs, o_attr, temp, b_ok
		Set Matches = AB.C.RegMatch(ohtml, s_ms & "(.+?)" & s_me)
		For Each Match In Matches
			b_ok = False
			tag = Trim(Match.SubMatches(0))
			If s_var_bef<>"" Then
				If b_var_bef Then '严格
					If AB.C.RegTest(tag, "^\"& s_var_bef &"(\w+)") Then
						tag = AB.C.RegReplace(tag, "^\"& s_var_bef &"(\w+)", "$1")
						b_ok = True
					End If
				Else
					tag = AB.C.RegReplace(tag, "^\"& s_var_bef &"(\w+)", "$1")
					b_ok = True
				End If
			End If
			attrs = AB.C.CRight(tag, " ")
			tag = AB.C.CLeft(tag, " ")
			If o_tag.Exists(tag) Then
				Set o_attr = tagAttr(attrs)
				temp = o_tag.Item(tag)
				temp = GetByAttr(temp, o_attr, "len") '属性: len
				temp = GetByAttr(temp, o_attr, "size") '属性: size
				If b_ok Then ohtml = Replace(ohtml, Match.Value, temp)
				Set o_attr = Nothing
			End If
		Next
		ParseMark_Common = ohtml
		On Error Goto 0
	End Function

	Public Function ParseMarkUnknown_Common(Byval html)
		On Error Resume Next
		Dim ohtml : ohtml = html
		Dim Matches, Match, temp
		Set Matches = AB.C.RegMatch(ohtml, s_ms & "(.+?)" & s_me)
		select case s_unknown
			case "keep"
				''Do Nothing
			case "remove"
				For Each Match In Matches
					ohtml = Replace(ohtml, Match.Value, "")
				Next
			case "comment"
				For Each Match In Matches
					temp = Match.SubMatches(0)
					ohtml = Replace(ohtml, Match.Value, "<!-- Unknown Tag '" & temp & "' -->")
				Next
		End select
		Set Matches = Nothing
		ParseMarkUnknown_Common = ohtml
		On Error Goto 0
	End Function

	'<<<---- <common tag> process e

	'---- <include tag> <template tag> process b --->>>
	'e.g.
	'标准写法1: {include "a.tpl"} 或 {include 'a.tpl'}  //无引号, 单引号或双引号都行
	'标准写法2: {include('a.tpl')} 或 {include ( 'a.tpl' ) }  //使用括号
	'旧版写法: {#include:a.tpl}  //兼容早期版本写法
	'其他写法: {template 'a.tpl'} 或 {template('a.tpl')}

	Private Function LoadInc(ByVal f, ByVal p)
		On Error Resume Next
		Dim h,pa,rule,inc,Match,incFile,incStr,temp
		f = SubTplPath(f)
		pa = AB.C.IIF(Left(f,1)="/","",p)
		If b_asp Then
			h = AB.C.GetInclude( pa & f )
		Else
			h = AB.C.Read( pa & f )
		End If
		'rule = "(<!--[\s]*)?" & s_ms & "#(include|template):(.+?)" & s_me & "([\s]*-->)?"
		rule = "(<!--[\s]*)?" & s_ms & "#?(include|template)[:|\s]?(.+?)" & s_me & "([\s]*-->)?"
		If AB.C.RegTest(h,rule) Then
			If AB.C.isNul(p) Then
				If Instr(f,"/")>0 Then p = Left(f,InstrRev(f,"/"))
			Else
				If Instr(f,"/")>0 Then p = pa & Left(f,InstrRev(f,"/"))
			End If
			Set inc = AB.C.RegMatch(h,rule)
			For Each Match In inc
				temp = Match.SubMatches(2)
				incFile = SubTplPath(temp)
				incStr = LoadInc(incFile, p)
				h = Replace(h,Match,incStr)
			Next
			Set inc = Nothing
		End If
		LoadInc = h
		On Error Goto 0
	End Function

	'<<<---- <include tag> <template tag> process e

	'---- <block tag> process b --->>>

	Public Function ParseMark_Block(Byval html)
		On Error Resume Next
		BlockEnd()
		Dim ohtml : ohtml = html
		ohtml = DoMarkBlock(ohtml)
		ParseMark_Block = ohtml
		On Error Goto 0
	End Function

	Public Function ParseMarkUnknown_Block(Byval html)
		On Error Resume Next
		Dim ohtml : ohtml = html
		Dim Matches, Match, rule, rule2, block, temp
		rule = "(<!--[\s]*)?(" & s_ms & ")#:(.+?)(" & s_me & ")([\s]*-->)?([\s\S]+?)(<!--[\s]*)?\2/#:\3\4([\s]*-->)?"
		'rule = "(<!--[\s]*)?(" & s_ms & ")#:(\w+)(?:[\s]*.*?)(" & s_me & ")([\s]*-->)?((?!\1\2#:\3)[\s\S]*)(<!--[\s]*)?\2/#:\3\4([\s]*-->)?"
		select case s_unknown
			case "keep"
				''Do Nothing
			case "remove"
				For Each block In o_blockdata
					rule2 = "(<!--[\s]*)?(" & s_ms & ")#:(" & block & ")(" & s_me & ")([\s]*-->)?([\s\S]+?)(<!--[\s]*)?\2/#:\3\4([\s]*-->)?"
					Set Matches = AB.C.regMatch(ohtml, rule2)
					For Each Match In Matches
						ohtml = Replace(ohtml, Match.Value, "")
					Next
				Next
				' Set Matches = AB.C.RegMatch(ohtml, rule)
				' For Each Match In Matches
					' ohtml = Replace(ohtml, Match.Value, "")
				' Next
				Set Matches = Nothing
			case "comment"
				For Each block In o_blockdata
					rule2 = "(<!--[\s]*)?(" & s_ms & ")#:(" & block & ")(" & s_me & ")([\s]*-->)?([\s\S]+?)(<!--[\s]*)?\2/#:\3\4([\s]*-->)?"
					Set Matches = AB.C.regMatch(ohtml, rule2)
					For Each Match In Matches
						ohtml = Replace(ohtml, Match.Value, "<!-- Unknown Block '" & block & "' -->")
					Next
				Next
				' Set Matches = AB.C.RegMatch(ohtml, rule)
				' For Each Match In Matches
					' temp = Match.SubMatches(2)
					' ohtml = Replace(ohtml, Match.Value, "<!-- Unknown Block '" & temp & "' -->")
				' Next
				Set Matches = Nothing
		End select
		ParseMarkUnknown_Block = ohtml
		On Error Goto 0
	End Function

	Private Function DoMarkBlock(ByVal s)
		On Error Resume Next
		Dim Matches, Match, block, tmp, temp, rule, tag, t_a, t_b : temp = s
		rule = "(<!--[\s]*)?(" & s_ms & ")#:(\w+)(?:[\s]*.*?)(" & s_me & ")([\s]*-->)?([\s\S]+?)(<!--[\s]*)?\2/#:\3\4([\s]*-->)?"
		' rule = "(<!--[\s]*)?(" & s_ms & ")#:(\w+)(?:[\s]*.*?)(" & s_me & ")([\s]*-->)?((?!\1\2#:\3)[\s\S]*)(<!--[\s]*)?\2/#:\3\4([\s]*-->)?"
		' Set Matches = AB.C.regMatch(s, rule)
		' For Each Match In Matches
			' tag = Trim(Match.SubMatches(2))
			' If o_blockdata.Exists(tag) Then
				' s = Replace(s, Match.Value, o_blockdata(tag))
			' End If
		' Next
		For Each block In o_blockdata
			Set Matches = AB.C.regMatch(temp, rule)
			For Each Match In Matches
				tag = Trim(Match.SubMatches(2))
				If o_blockdata.Exists(tag) Then
					temp = Replace(temp, Match.Value, s_bx & tag & s_by)
				End If
			Next
		Next
		rule = s_bx & "(\w+?)" & s_by
		Set Matches = AB.C.regMatch(temp, rule)
		For Each Match In Matches
			tag = Trim(Match.SubMatches(0))
			If o_blockdata.Exists(tag) Then
				If o_update.Exists(tag) Then
					temp = Replace(temp, Match.Value, o_blockdata(tag))
				Else
					t_a = AB.C.CLeft(o_blockfull_b(tag), "[*]")
					t_b = AB.C.CRight(o_blockfull_b(tag), "[*]")
					temp = Replace(temp, Match.Value, t_a & o_blockdata(tag) & t_b)
				End If
			End If
		Next
		s = temp
		DoMarkBlock = s
		On Error Goto 0
	End Function

	'------------------------------------------------------------------------------------------
	'# AB.Tpl.Update 方法
	'# @syntax: AB.Tpl.Update tagname
	'# @return: 无返回值
	'# @dowhat: 用于循环更新替换标签块
	'--DESC------------------------------------------------------------------------------------
	'# @param tagname : 循环替换标签名
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "tpl" '加载tpl核心
	'# Dim tpl : Set tpl = AB.Tpl.New '创建一个Tpl对象
	'# tpl.TagMask = "{{*}}"
	'# tpl.LoadStr "<h3>Request.ServerVariables变量值列表</h3><br>{{table}}"
	'# tpl.TagStr "table", "<table border=""1""><thead><tr><th width=""20%"">{{cname}}</th><th width=""80%"">{{cvalue}}</th></tr></thead>{{#:loop}}<tr><th>{{name}}</th><td>{{value}}</td></tr>{{/#:loop}}</table>"
	'# tpl "cname", "名称"
	'# tpl "cvalue", "值"
	'# Dim i
	'# For Each i In Request.ServerVariables
	'# 	tpl "name", i
	'# 	tpl "value", AB.C.HtmlEncode(Request.ServerVariables(i)) & "&nbsp;"
	'# 	tpl.Update "loop"
	'# Next
	'# tpl.Show()
	'# Set tpl = Nothing '释放Tpl对象
	'------------------------------------------------------------------------------------------

	Public Sub [Update](ByVal b)
		On Error Resume Next
		Dim Matches, Match, tmp, temp, block, rule, tag
		If o_update.Exists(b) Then
			If Not IsNumeric(o_update(b)) Then o_update(b) = 0
			o_update(b) = CLng(o_update(b)) + 1
		Else
			o_update.Add b, 1
		End If
		If b_update_block = False Then
			rule = "(<!--[\s]*)?(" & s_ms & ")#:(\w+)(?:[\s]*.*?)(" & s_me & ")([\s]*-->)?([\s\S]+?)(<!--[\s]*)?\2/#:\3\4([\s]*-->)?"
			For Each block In o_blockdata_b
				tmp = o_blockdata_b.Item(block)
				Set Matches = AB.C.regMatch(tmp, rule)
				For Each Match In Matches
					tag = Trim(Match.SubMatches(2))
					If o_blockdata_b.Exists(tag) Then
						tmp = Replace(tmp, Match.Value, s_bx & tag & s_by)
					End If
				Next
				o_blockdata_b(block) = tmp
			Next
			Set o_blockdata = AB.C.CloneDict(o_blockdata_b)
		End If
		SetBlockData b
		ClearSubBlockData b
		b_update_block = True
		On Error Goto 0
	End Sub

	Private Sub SetBlockData(ByVal b)
		On Error Resume Next
		Dim Matches, Match, temp, elem, rule, data, tag
		rule = s_bx & "(\w+?)" & s_by
		If o_blockdata_b.Exists(b) Then
			temp = o_blockdata_b.Item(b)
			If o_update.Exists(b) Then temp = UpdateBlockTag(temp)
			If o_update.Exists(b) Then
				If o_update(b) = 1 Then
					o_blockdata(b) = temp
				Else
					o_blockdata(b) = UpdateBlockTag(o_blockdata(b)) & temp
				End If
			End If
		End If
		For Each elem In o_blockdata
			temp = o_blockdata.Item(elem)
			Set Matches = AB.C.regMatch(temp, rule)
			For Each Match In Matches
				tag = Match.SubMatches(0)
				If o_blockdata.Exists(tag) Then
					data = o_blockdata(tag)
					temp = Replace(temp, Match.Value, data)
				End if
			Next
			o_blockdata(elem) = temp
		Next
		On Error Goto 0
	End Sub

	Private Sub ClearSubBlockData(ByVal b)
		On Error Resume Next
		Dim Matches, Match, temp, elem, rule, data, tag
		rule = s_bx & "(\w+?)" & s_by
		If o_blockdata_b.Exists(b) Then
			temp = o_blockdata_b.Item(b)
			If AB.C.RegTest(temp, rule) Then
				Set Matches = AB.C.regMatch(temp, rule)
				For Each Match In Matches
					tag = Match.SubMatches(0)
					If o_blockdata.Exists(tag) Then
						If b_update_block Then o_blockdata(tag) = ""
					End If
				Next
			End If
		End If
		On Error Goto 0
	End Sub

	Private Sub BlockEnd()
		On Error Resume Next
		Dim Matches, Match, temp, elem, rule, data, tag, t_a, t_b
		rule = s_bx & "(\w+?)" & s_by
		For Each elem In o_blockdata
			temp = o_blockdata.Item(elem)
			Set Matches = AB.C.regMatch(temp, rule)
			For Each Match In Matches
				tag = Match.SubMatches(0)
				If o_blockdata.Exists(tag) Then
					data = o_blockdata(tag)
					If o_update.Exists(tag) Then
						temp = Replace(temp, Match.Value, data)
					Else
						t_a = AB.C.CLeft(o_blockfull_b(tag), "[*]")
						t_b = AB.C.CRight(o_blockfull_b(tag), "[*]")
						temp = Replace(temp, Match.Value, t_a & data & t_b)
					End If
				End if
			Next
			o_blockdata(elem) = temp
		Next
		On Error Goto 0
	End Sub

	Private Function UpdateBlockTag(ByVal s)
		On Error Resume Next
		Dim Matches, Match, data, rule
		Set Matches = AB.C.RegMatch(s, s_ms & "(.+?)" & s_me)
		For Each Match In Matches
			data = Match.SubMatches(0)
			If o_tag.Exists(data) Then
				rule = Match.Value
				If AB.C.isNul(o_tag.Item(data)) Then
					s = Replace(s, rule, "")
				Else
					s = Replace(s, rule, o_tag.Item(data))
				End If
			End If
			If o_attr.Exists(data) Then
				rule = Match.Value
				If AB.C.isNul(o_attr.Item(data)) Then
					s = Replace(s, rule, "")
				Else
					s = Replace(s, rule, o_attr.Item(data))
				End If
			End If
		Next
		UpdateBlockTag = s
		On Error Goto 0
	End Function

	Private Function SetBlocks(Byval s)
		On Error Resume Next
		Dim Matches, Match, rule, n, i, j : i = 0
		rule = "(<!--[\s]*)?" & s_ms & "#:(.+?)" & s_me
		If Not AB.C.RegTest(s, rule) Then : SetBlocks = s : Exit Function : End If
		Set Matches = AB.C.regMatch(s,rule)
		For Each Match In Matches
			n = Match.SubMatches(1)
			If o_blocks.Exists(i) Then o_blocks.Remove i
			o_blocks.Add i, n
			i = i + 1
		Next
		Dim temp : temp = s
		For j = i-1 To 0 Step -1
			temp = BlockBegin(temp, o_blocks.item(j))
		Next
		SetBlocks = s
		On Error Goto 0
	End Function

	Private Function BlockBegin(Byval s, ByVal b)
		On Error Resume Next
		Dim Matches, Match, rule, data, attrs, attr, att, aname, avalue, atag
		rule = "(<!--[\s]*)?(" & s_ms & ")#:(" & b & ")(" & s_me & ")([\s]*-->)?([\s\S]+?)(<!--[\s]*)?\2/#:\3\4([\s]*-->)?"
		If Instr(b," ")>0 Then
			attrs = AB.C.CRight(b, " ")
			b = AB.C.CLeft(b, " ")
		  rule = "(<!--[\s]*)?(" & s_ms & ")#:(" & b & " " & AB.C.RegEncode(attrs) & ")(" & s_me & ")([\s]*-->)?([\s\S]+?)(<!--[\s]*)?\2/#:" & b & "\4([\s]*-->)?"
		End If
		Set Matches = AB.C.regMatch(s, rule)
		For Each Match In Matches
			data = Match.SubMatches(5)
			If o_blockdata_b.Exists(b) Then
				o_blockfull_b.Remove(b)
				o_blockdata_b.Remove(b)
				o_block.Remove(b)
			End If
			o_blockdata_b.Add b, Cstr(data)
			o_blockfull_b.Add b, Replace(Match.Value, data, "[*]")
			o_block.Add b, Cstr(b)
			s = Replace(s, Match.Value, s_bx & b & s_by)
			If AB.C.Has(attrs) Then
				' Set attr = AB.C.RegMatch(attrs, "((\w+)=(['""])(.+?)\3)|((\w+)=([^\s]+))")
				' For Each att In attr
					' aname = AB.C.CLeft(att.Value, "=")
					' avalue = AB.C.RegReplace(att.Value, "\w+=(['""]?)(.+?)\1", "$2")
					' atag = b & "." & aname
					' If o_attr.Exists(atag) Then o_attr.Remove(atag)
					' o_attr.Add atag, avalue
				' Next
				Set attr = tagAttr(attrs)
				For Each att In attr
					aname = att
					avalue = attr(att)
					atag = b & "." & aname
					If o_attr.Exists(atag) Then o_attr.Remove(atag)
					o_attr.Add atag, avalue
				Next
				Set attr = Nothing
			End If
		Next
		BlockBegin = s
		On Error Goto 0
	End Function

	'<<<---- <block tag> process e

	'---- <if tag> process b --->>>

	Public Function ParseMark_If(Byval html)
		On Error Resume Next
		Dim ohtml : ohtml = html
		ParseMark_If = DoMarkIf(ohtml)
		On Error Goto 0
	End Function

	Private Function DoMarkIf(ByVal s)
		On Error Resume Next
		DoMarkIf = LogicReplace(s)
		On Error Goto 0
	End Function

	Private Function LogicReplace(ByVal s)
		On Error Resume Next
		Dim Matches, Match, result, condi, conds, cond, n, yes, no, x, e, f, cname, ckey, copera, cvalue
		Set Matches = AB.C.RegMatch(s, s_ms & "#if\s+(.+?)"&s_me&"([\s\S]+?)(?:"&s_ms&"#else"&s_me&"([\s\S]+?))?"&s_ms&"/#if"&s_me)
		For Each Match In Matches
			condi = Match.SubMatches(0)
			yes = Match.SubMatches(1)
			no = Match.SubMatches(2)
			'Set conds = AB.C.RegMatch(condi,"(?:([^&)(\s}|}=<>!]+)([=<>!]{1,2})(['""])(.+?)\3)|(?:([^&()\s|}=<>!]+)([=<>!]{1,2})([^&)\s|}]+))")
			Set conds = AB.C.RegMatch(condi,"(?:([^&)(\s}|}=<>!]+)([=<>!]{1,2}\s*)(\s*['""])(.*?)\3)|(?:([^&()\s|}=<>!]+\s*)([=<>!]{1,2})(\s*[^&)\s|}]+))")
			For Each cond In conds
				cname = cond.Value
				Set e = AB.C.RegMatch(cname,"@([\w\.]+)")
				For Each f In e
					n = f.SubMatches(0)
					cname = Replace(cname, f.Value, AB.C.IIF(o_tag.Exists(n),o_tag.Item(n),""))
				Next
				Set e = Nothing
				'Set x = AB.C.RegMatch(cname,"^([^=<>!]*)([=<>!]{1,2})(['""]?)(.*)\3$")
				Set x = AB.C.RegMatch(cname,"^([^=<>!]*)\s*([=<>!]{1,2})\s*(['""]?)(.*)\3$")
				ckey = x(0).SubMatches(0)
				copera = x(0).SubMatches(1)
				cvalue = x(0).SubMatches(3)
				condi = Replace(condi, cond.Value, Comp(ckey,copera,cvalue))
				condi = Replace(condi, "&&", " And ")
				condi = Replace(condi, "||", " Or ")
				Set x = Nothing
			Next
			s = Replace(s, Match.Value, AB.C.IIF(Eval(condi), yes, no))
			Set conds = Nothing
		Next
		Set Matches = Nothing
		LogicReplace = s
		On Error Goto 0
	End Function

	Private Function Comp(ByVal k, ByVal o, ByVal v)
		On Error Resume Next
		Dim tmp,m,ma,mb : tmp = False
		Select Case o
			Case "=","=="
				m = Replace(k,"\%","")
				If Instr(m,"%")>0 Then
					ma = AB.C.CLeft(m,"%")
					mb = AB.C.CRight(m,"%")
					tmp = (CLng(ma) Mod CLng(mb) = v)
				Else
					tmp = (CStr(k) = CStr(v))
				End If
			Case "<>","!=" tmp = (CStr(k) <> CStr(v))
			Case ">=" tmp = (CDbl(k) >= CDbl(v))
			Case "<=" tmp = (CDbl(k) <= CDbl(v))
			Case ">" tmp = (CDbl(k) > CDbl(v))
			Case "<" tmp = (CDbl(k) < CDbl(v))
		End Select
		Comp = AB.C.IIF(Err.Number=0,tmp,False)
		On Error Goto 0
	End Function

	'<<<---- <if tag> process e

	Public Function MakeTag(ByVal t, ByVal f)
		On Error Resume Next
		Dim s,p,e,a,b,i,m : b = Array()
		If Instr(t,":")>0 Then
			m = AB.C.CRight(t,":")
			t = AB.C.CLeft(t,":")
			m = AB.C.DateTime(Now,m)
		End If
		If IsArray(f) Then a = f Else a = Split(f,"|")
		For i = 0 To Ubound(a)
			a(i) = s & Trim(a(i)) & AB.C.IfThen(AB.C.Has(m),"?" & m) & e
		Next
		Select Case Lcase(t)
			Case "css"
				p = "<link href=""{css}"" rel=""stylesheet"" type=""text/css"" />"
				i = 0
				For Each e In a
					If Trim(e) <> "" Then
						Redim Preserve b(i)
						b(i) = Replace(p, "{css}", Trim(e))
						i = i + 1
					End If
				Next
				s = Join(b,vbCrLf)
			Case "js"
				p = "<scr"&"ipt type=""text/javascript"" src=""{js}""></scr"&"ipt>"
				i = 0
				For Each e In a
					If Trim(e) <> "" Then
						Redim Preserve b(i)
						b(i) = Replace(p, "{js}", Trim(e))
						i = i + 1
					End If
				Next
				s = Join(b,vbCrLf)
			Case "author", "keywords", "description", "copyright", "generator", "revised", "others"
				s = MakeTagMeta("name",t,f)
			Case "content-type", "expires", "refresh", "set-cookie"
				s = MakeTagMeta("http-equiv",t,f)
			Case "title"
				s = "<title>"&f&"</title>"
			Case "charset"
				If IsNull(f) Or Trim(f) = "" Then f = s_charset
				s = "<meta http-equiv=""Content-Type"" content=""text/html; charset="&f&""" /> "
		End Select
		MakeTag = s
		On Error Goto 0
	End Function

	Public Function tagAttr(Byval s)
		On Error Resume Next
		Dim o_attr, Matches, Match, k, v
		Set o_attr = Server.CreateObject(s_dict) : o_attr.CompareMode = 1
		s = Replace(s, "\\", Chr(26))
		s = Replace(s, "\'", Chr(27))
		s = Replace(s, "\""", Chr(28))
		Set Matches = AB.C.RegMatch(s, "(\w+)=(" & "(['""]?)([^\s]+|.*?)\3" & ")")
		For Each Match In Matches
			k = LCase(Match.SubMatches(0))
			v = Match.SubMatches(3)
			v = Replace(v, Chr(28), """")
			v = Replace(v, Chr(27), "'")
			v = Replace(v, Chr(26), "\")
			o_attr.Remove k
			o_attr(k) = v
		Next
		Set Matches = Nothing
		Set tagAttr = o_attr
		On Error Goto 0
	End Function

	Public Function GetByAttr(Byval s, Byval o_attr, Byval attr)
		On Error Resume Next
		If Not AB.C.IsDict(o_attr) Then : GetByAttr = s : Exit Function : End If
		Dim i_len, i_size : i_len=0 : i_size=0
		Select Case LCase(attr)
			Case "len" :
				If Err Then Err.Clear
				i_len = 0
				If o_attr.Exists("len") Then i_len = CLng(o_attr("len"))
				If Err.Number<>0 Then i_len=0
				If i_len>0 Then s = Left(s, i_len)
			Case "size" :
				If Err Then Err.Clear
				i_size = 0
				If o_attr.Exists("size") Then i_size = CLng(o_attr("size"))
				If Err.Number<>0 Then i_size=0
				If i_size>0 Then s = AB.C.CutStr(s, ""& i_size &":")
			Case Else :
				GetByAttr = s
		End Select
		GetByAttr = s
		On Error Goto 0
	End Function

	'---- {other tag} process b --->>>

	Public Function replace_html(ByVal s)
		On Error Resume Next
		Dim str : str = s
		'过滤 <!--{}-->
		'str = AB.C.RegReplace(str,"(?:\<!--[\s]*)(" & s_ms & ")(.+?)(" & s_me & ")(?:[\s]*-->)", "$1$2$3")
		'-- ASP脚本解析处理 b：
		''str = html_get(str, 1)
		'str = html_get(str, 0)
		'-- e --
		replace_html = str
	End Function

	'<<<---- {other tag} process e

	'---- [vb-html] process b --->>>

    '获取vb代码(html转vb)
	Public Function vb_get(ByVal s, ByVal p)
		On Error Resume Next
		If Err Then Err.Clear
		Dim str, tmp, a, b, t, tstr, vb : str = s
		If AB.C.IsNul(str) Then : vb_get = "" : Exit Function : End If
		If IsNull(p) Or Trim(p)="" Then p = 0
		If p = 0 Then
			tmp = "Dim tmd : tmd = """""&vbcrlf
			a = 1 : b = instr(a,str,"<"&"%")+2
			While b > a+1
				t = mid(str,a,b-a-2)
				t = replace(t,"""","""""")
				t = AB.C.RP(t, Array(vbcrlf,vblf,vbcr), Array(""" & VbCrlf & """,""" & VbCrlf & """,""))
				tmp = tmp & "tmd = tmd & """ & t & """" & vbcrlf
				a = instr(b,str,"%"&">")+2
				tstr = mid(str,b,a-b-2)
				tstr = AB.C.RegReplace(tstr,"^\s*=","tmd = tmd & ")
				tstr = AB.C.RegReplaceM(tstr, "^\s*[\r\n]+\s*(rem|').*$", "")
				tstr = RegReplaceM(tstr, "(\s+?rem[\t ]+|\s*\')((?!"").)*$", "") '去掉行尾注释
				'tstr = AB.C.RegReplaceM(tstr, "^\s*(.*)\s*$", "$1") '删除首空格以及空行
				'tstr = AB.C.RegReplaceM(tstr, "^(.*?)[ \t]+$", "$1") '删除尾空格
				tmp = tmp & tstr & vbcrlf
				b = instr(a,str,"<"&"%")+2
			Wend
			t = mid(str,a)
			t = replace(t,"""","""""")
			t = AB.C.RP(t, Array(vbcrlf,vblf,vbcr), Array(""" & VbCrlf & """,""" & VbCrlf & """,""))
			tmp = tmp & "tmd = tmd & """ & t & """" & vbcrlf
			tmp = replace(tmp,"ab.c.println","tmd = tmd & VbCrlf & """" & ",1,-1,1)
			tmp = replace(tmp,"ab.c.printcn","tmd = tmd & "& """<br /"&">"" & VbCrlf & """" & ",1,-1,1)
			tmp = replace(tmp,"ab.c.wnh","tmd = ab.c.htmlencode(tmd) & "& """<br /"&">"" & VbCrlf & """" & ",1,-1,1)
			tmp = replace(tmp,"ab.c.wr","tmd = tmd & "& """<br /"&">"" & VbCrlf & """" & ",1,-1,1)
			tmp = replace(tmp,"ab.c.wn","tmd = tmd & VbCrlf & """" & ",1,-1,1)
			'- echo -
			tmp = replace(tmp,"response.write","tmd = tmd & ",1,-1,1)
			tmp = replace(tmp,"ab.c.print","tmd = tmd & ",1,-1,1)
			tmp = replace(tmp,"ab.c.echo","tmd = tmd & ",1,-1,1)
			tmp = replace(tmp,"ab.c.w","tmd = tmd & ",1,-1,1)
			vb = tmp
		Else
			Dim rule : rule = "\<"&"%([\s\S]*?)%"&"\>"
			Dim temp, subset : subset = Array()
			Dim arr : arr = AB.C.RegSplit(str, rule, 1)
			AB.Use "A"
			For i=0 To UBound(arr)
				temp = ""
				If AB.C.RegTest(arr(i), rule) Then
					temp = AB.C.RegReplace(arr(i), rule, "$1")
					temp = AB.C.RegReplaceM(temp, "^\s*[\r\n]+\s*(rem|').*$", "")
					temp = AB.C.RegReplaceM(temp, "^\s*[\r\n]+\s*$", "")
					temp = AB.C.RegReplace(temp,"^\s*=\s*","Response.Write ")
					'temp = AB.C.RP(temp, Array(vbcrlf,vblf,vbcr), Array(":",":",""))
					temp = AB.C.RP(temp, Array(vbcrlf,vblf,vbcr), Array(VbCrlf,VbCrlf,""))
					subset = AB.A.Push(subset, temp)
				Else
					temp = arr(i)
					temp = Replace(temp, """", """""")
					temp = AB.C.RP(temp, Array(vbcrlf,vblf,vbcr), Array(""" & VbCrlf & """,""" & VbCrlf & """,""))
					temp = "Response.Write("""& temp &""")"
					subset = AB.A.Push(subset, temp)
				End If
			Next
			'vb = ""& Join(subset, " : ") & ""
			vb = ""& Join(subset, VbCrlf) & ""
			''vb = AB.C.RegReplace(vb, "[""]([^""]*)""", """""$1""""")
			'ab.c.print Replace(vb, """", """""") '用于调试
		End If
		vb_get = vb
		On Error Goto 0
	End Function

	Public Function html_get(ByVal s, ByVal p)
		On Error Resume Next
		If Err Then Err.Clear
		Dim str, temp : str = s
		If IsNull(p) Or Trim(p)="" Then p = 0
		If p = 0 Then
			temp = vb_get(str, 0)
			Dim tmd
			Execute(temp)
			str = tmd
		ElseIf p = 1 Then
			'转为vb脚本,执行解析,http获取客户端解析代码
			temp = vb_get(str, 1)
			If Request.QueryString(s_rq_show)="true" Then
				Response.Clear
				Execute(temp)
				Response.End
			End If
			Dim s_tplshow : s_tplshow = GetPathUrl & "" & AB.C.GetUrlWith("-"& s_rq_show, s_rq_show &"=true")
			AB.Use "Http"
			Dim h : Set h = AB.Http.New
			str = h.Get(s_tplshow)
			Set h = Nothing
		ElseIf p = 2 Then
			temp = vb_get(str, 1)
			Dim tpl_cache_dir : tpl_cache_dir = "/_cache/template_c/"
			Dim tpl_cache_file : tpl_cache_file = "cachefile_tpl_1.asp"
			AB.Use "fso"
			If AB.Fso.CreateFile(tpl_cache_dir&tpl_cache_file, "<"&"% "& temp &" %"&">") Then
				Server.Execute(tpl_cache_dir&tpl_cache_file)
				str = ""
			End If
		End If
		'If Err Then : Err.Clear : str = s : End If
		html_get = str
		On Error Goto 0
	End Function

	'<<<---- [vb-html] process e

	'==== 辅助函数 ====

	Private Function MakeTagMeta(ByVal m, ByVal t, ByVal s)
		MakeTagMeta = "<meta " & m & "=""" & t & """ content=""" & s & """ /"&">"
	End Function

	Private Sub getMaskSE(ByVal m)
		On Error Resume Next
		s_ms = AB.C.RegEncode(AB.C.CLeft(m,"*"))
		s_me = AB.C.RegEncode(AB.C.CRight(m,"*"))
		On Error Goto 0
	End Sub

	Private Function SubTplPath(ByVal f)
		f = AB.C.RegReplace(f, "\((.+?)\)", "$1")
		f = AB.C.RegReplace(f, "'(.+?)'", "$1")
		f = AB.C.RegReplace(f, """(.+?)""", "$1")
		f = Trim(f)
		SubTplPath = f
	End Function

	Private Function GetVar(ByVal var)
	    Execute("Function GetVarValue(): GetVarValue=" & var  & ": End Function")
	    GetVar = GetVarValue()
	    'GetVar = Eval(""& var)
	End Function

	Private Function Var(Byval s)
		On Error Resume Next
		Dim Matches, Match, temp, rule
		rule = "^[\$]?(\w+)$"
		If AB.C.RegTest(s, rule) Then
			s = AB.C.RegReplace(s, rule, "$1")
			temp = GetVar(s)
			If o_attr.Exists(s) Then temp = o_attr.Item(s)
			If o_tag.Exists(s) Then temp = o_tag.Item(s)
		End If
		Var = temp
		On Error Goto 0
	End Function

	Private Function CDVar(Byval s)
		On Error Resume Next
		Dim Matches, Match, v
		's = AB.C.RegReplace(s,"\$(\w+)", "$1")
		Set Matches = AB.C.RegMatch(s, "\$(\w+)")
		For Each Match In Matches
			v = Match.SubMatches(0)
			If o_tag.Exists(v) Then v = o_tag.Item(v)
			s = Replace(s, Match.Value, ""& v &"")
		Next
		Set Matches = Nothing
		CDVar = s
		On Error Goto 0
	End Function

	Private Function CQVar(Byval s)
		On Error Resume Next
		Dim Matches, Match, v
		s = Replace(s, "\\", Chr(26))
		s = Replace(s, "\]", Chr(25))
		s = Replace(s, "\[", Chr(24))
		Set Matches = AB.C.RegMatch(s, "" & "(['""])([^\1]*?)\1" & "")
		For Each Match In Matches
			v = Match.SubMatches(1)
			v = AB.C.RegReplace(v,"\[\$?(\w+)]", """& "& "$1" &" &""")
			v = AB.C.RegReplace(v,"\$(\w+)", """& "& "$1" &" &""")
			s = Replace(s, Match.Value, """"& v &"""")
		Next
		s = Replace(s, Chr(26), "\")
		s = Replace(s, Chr(25), "]")
		s = Replace(s, Chr(24), "[")
		Set Matches = Nothing
		CQVar = s
		On Error Goto 0
	End Function

	Private Function CEVar(Byval s)
		CEVar = RPQuote(s, 2)
	End Function

	Private Function CSVar(Byval s)
		CSVar = RPQuote(s, 1)
	End Function

	Private Function CQuote(Byval s)
		CQuote = RPQuote(s, 0)
	End Function

	Private Function RPQuote(ByVal s, ByVal p)
		On Error Resume Next
		If IsNull(p) Or Trim(p)="" Then p = 0
		Dim Matches, Match, v
		s = Replace(s, "\\", Chr(26))
		s = Replace(s, "\'", Chr(27))
		s = Replace(s, "\""", Chr(28))
		Set Matches = AB.C.RegMatch(s, "" & "(['""])([^\1]*?)\1" & "")
		For Each Match In Matches
			v = Match.SubMatches(1)
			If p=0 Then v = Replace(v, """", """""")
			If p=1 Or p=2 Then v = Replace(v, ";", Chr(29))
			s = Replace(s, Match.Value, """"& v &"""")
		Next
		If p=2 Then s = Replace(s, ";", ":")
		If p=1 Or p=2 Then s = Replace(s, Chr(29), ";")
		s = Replace(s, Chr(28), """""")
		s = Replace(s, Chr(27), "'")
		s = Replace(s, Chr(26), "\")
		Set Matches = Nothing
		RPQuote = s
		On Error Goto 0
	End Function

	Private Function CstrComp(ByVal k, ByVal o, ByVal v)
		On Error Resume Next
		Dim tmp : tmp = ""
		tmp = k & o & v
		CstrComp = tmp
		On Error Goto 0
	End Function

	Private Function SymbolComp(ByVal o)
		On Error Resume Next
		Dim tmp : tmp = o
		Select Case tmp
			Case "=","==" tmp = "="
			Case "<>","!=" tmp = "<>"
			Case ">=" tmp = ">="
			Case "<=" tmp = "<="
			Case ">" tmp = ">"
			Case "<" tmp = "<"
		End Select
		SymbolComp = tmp
		On Error Goto 0
	End Function

	Private Function GetPathUrl
		Dim ustart, uport
		If AB.C.RqSv("HTTPS")="on" Then
			ustart = "https://"
			uport = AB.C.IIF(Int(AB.C.RqSv("SERVER_PORT"))=443,"",":"&AB.C.RqSv("SERVER_PORT"))
		Else
			ustart = "http://"
			uport = AB.C.IIF(Int(AB.C.RqSv("SERVER_PORT"))=80,"",":"&AB.C.RqSv("SERVER_PORT"))
		End If
		Dim url : url = ustart & AB.C.RqSv("SERVER_NAME") & uport
		GetPathUrl = url
	end Function

End Class

Class Cls_AB_Tpl_Fn

	Private s_dict
	Private o_dict

	Private Sub class_Initialize
		s_dict = AB.dictName
		Set o_dict = Server.CreateObject(s_dict) : o_dict.CompareMode = 1
	End Sub

	Private Sub Class_Terminate
		Set o_dict = Nothing
	End Sub

	Public Sub Echo(ByVal s) '引用PHP输出
		Response.Write s
	End Sub

End Class
%>